﻿using EnvDTE;
using EnvDTE80;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using System;
using System.ComponentModel.Design;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using Task = System.Threading.Tasks.Task;

namespace GetEnumsDemo
{
    /// <summary>
    /// Command handler
    /// </summary>
    internal sealed class Command1
    {
        /// <summary>
        /// Command ID.
        /// </summary>
        public const int CommandId = 0x0100;

        /// <summary>
        /// Command menu group (command set GUID).
        /// </summary>
        public static readonly Guid CommandSet = new Guid("2f927a9e-1b49-432b-817c-5f27536121ab");

        /// <summary>
        /// VS Package that provides this command, not null.
        /// </summary>
        private readonly AsyncPackage package;

        /// <summary>
        /// Initializes a new instance of the <see cref="Command1"/> class.
        /// Adds our command handlers for menu (commands must exist in the command table file)
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        /// <param name="commandService">Command service to add command to, not null.</param>
        private Command1(AsyncPackage package, OleMenuCommandService commandService)
        {
            this.package = package ?? throw new ArgumentNullException(nameof(package));
            commandService = commandService ?? throw new ArgumentNullException(nameof(commandService));

            var menuCommandID = new CommandID(CommandSet, CommandId);
            var menuItem = new MenuCommand(Execute, menuCommandID);
            commandService.AddCommand(menuItem);
        }

        /// <summary>
        /// Gets the instance of the command.
        /// </summary>
        public static Command1 Instance
        {
            get;
            private set;
        }

        /// <summary>
        /// Gets the service provider from the owner package.
        /// </summary>
        private Microsoft.VisualStudio.Shell.IAsyncServiceProvider ServiceProvider
        {
            get
            {
                return this.package;
            }
        }

        /// <summary>
        /// Initializes the singleton instance of the command.
        /// </summary>
        /// <param name="package">Owner package, not null.</param>
        public static async Task InitializeAsync(AsyncPackage package)
        {
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync(package.DisposalToken);

            OleMenuCommandService commandService = await package.GetServiceAsync(typeof(IMenuCommandService)) as OleMenuCommandService;
            Instance = new Command1(package, commandService);
        }
        // 同步的
        private void Execute(object sender, EventArgs e)
        {
            _ = ExecuteAsync(sender, e);
        }

        private async Task ExecuteAsync(object sender, EventArgs e)
        {
            //ThreadHelper.ThrowIfNotOnUIThread();
            await ThreadHelper.JoinableTaskFactory.SwitchToMainThreadAsync();
            // package获取
            var _dTE = await package.GetServiceAsync(typeof(DTE)) as DTE2;
            if (_dTE == null)
                return;
            var doc = _dTE.ActiveDocument;
            if (doc == null)
                return;
            var fcm = doc.ProjectItem.FileCodeModel as FileCodeModel;
            if (fcm == null)
                return;
            var clms = fcm.CodeElements;
            if (clms == null)
                return;
            for (int i = 1; i < clms.Count; i++)
            {
                var clm = clms.Item(i);
                if (clm == null)
                    continue;

                if (clm.Kind != vsCMElement.vsCMElementNamespace)
                    continue;

                var subcls = clm.Children;
                if (subcls == null)
                    continue;

                foreach (CodeElement subclm in subcls)
                {
                    //VsShellUtilities.ShowMessageBox(this.package, subclm.Kind.ToString(), "提示", OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                    if (subclm.Kind == vsCMElement.vsCMElementEnum)
                    {
                        var objEp = subclm.StartPoint.CreateEditPoint();
                        var text = objEp.GetText(subclm.EndPoint);
                        VsShellUtilities.ShowMessageBox(this.package, text, "提示", OLEMSGICON.OLEMSGICON_INFO, OLEMSGBUTTON.OLEMSGBUTTON_OK, OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
                        var subChild = subclm.Children;
                        if (subChild != null)
                        {
                            foreach (CodeElement child in subChild)
                            {

                            }
                        }

                    }
                }

            }
            string message = string.Format(CultureInfo.CurrentCulture, "Inside {0}.MenuItemCallback()", this.GetType().FullName);
            string title = "Command1";

            // Show a message box to prove we were here
            VsShellUtilities.ShowMessageBox(
                this.package,
                message,
                title,
                OLEMSGICON.OLEMSGICON_INFO,
                OLEMSGBUTTON.OLEMSGBUTTON_OK,
                OLEMSGDEFBUTTON.OLEMSGDEFBUTTON_FIRST);
        }
    }
}
